package com.project.web.order.service.impl.app;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.project.common.core.config.prop.PropAttributes;
import com.project.common.core.config.prop.PropConfig;
import com.project.common.core.utils.Ali.AliPayPojo;
import com.project.common.core.utils.Ali.AliPayUtil;
import com.project.common.core.utils.DateUtil;
import com.project.common.core.utils.id.IDUtil;
import com.project.common.core.utils.id.OrderNoWorker;
import com.project.common.core.utils.weChat.WeChatPayUtil;
import com.project.web.course.service.impl.common.BaseServiceImpl;
import com.project.web.order.mapper.app.CartMapper;
import com.project.web.order.mapper.app.MbrOrderItemMapper;
import com.project.web.order.mapper.app.MbrOrderLogMapper;
import com.project.web.order.mapper.app.MbrOrderMapper;
import com.project.web.order.model.app.MbrOrder;
import com.project.web.order.model.app.MbrOrderItem;
import com.project.web.order.model.app.MbrOrderLog;
import com.project.web.order.model.app.vo.MbrOrderInfoVO;
import com.project.web.order.model.app.vo.MbrOrderPayVO;
import com.project.web.order.service.app.MbrOrderService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @ClassName CourseOrderServiceImpl
 * @Description
 * @Author WYY
 * @Date 2020/10/16 4:24 PM
 * @Version 1.0
 */
@Service("mbrOrderServiceImpl")
public class MbrOrderServiceImpl extends BaseServiceImpl<MbrOrder, Long> implements MbrOrderService {

    @Autowired
    private MbrOrderMapper mbrOrderMapper;

    @Autowired
    private MbrOrderItemMapper mbrOrderItemMapper;

    @Autowired
    private MbrOrderLogMapper mbrOrderLogMapper;

    @Override
    public PageInfo<MbrOrder> getPageList(MbrOrder courseOrder, Page page) {
        PageHelper.startPage(page.getPageNum(), page.getPageSize());
        List<MbrOrder> courseOrders = mbrOrderMapper.selectList(courseOrder);
        return new PageInfo<>(courseOrders);
    }

    /**
     * App统一下单
     *
     * @param mbrOrderPayVO 会员订单支付VO对象
     * @param request       request请求对象
     * @return
     */
    @Override
    public Map<String, Object> handleMbrOrderOfApp(MbrOrderPayVO mbrOrderPayVO, HttpServletRequest request) {
        // 如果订单号存在就直接下单
        String orderNo = mbrOrderPayVO.getOrderNo();
        if (StringUtils.isBlank(orderNo)) {
            // 保存订单数据
            orderNo = OrderNoWorker.get();
            MbrOrder mbrOrder = new MbrOrder();
            mbrOrder.setId(IDUtil.getId());
            mbrOrder.setOrderNo(orderNo);
            mbrOrder.setTotalAmt(mbrOrderPayVO.getTotalAmt());
            mbrOrder.setActualAmt(mbrOrderPayVO.getActualAmt());
            mbrOrder.setPayMode(mbrOrderPayVO.getPayMode());
            mbrOrder.setOrderStatus(MbrOrder.ORDER_STATUS.NOT_PAY.getValue());
            mbrOrder.setOrderRemark("App订单");
            mbrOrder.setOrderType(mbrOrderPayVO.getOrderType());
            mbrOrder.setUserId(mbrOrderPayVO.getUserId());
            mbrOrder.setCreateDate(new Date());
            mbrOrderMapper.save(mbrOrder);

            // 保存订单项表
            MbrOrderItem mbrOrderItem = new MbrOrderItem();
            mbrOrderItem.setId(IDUtil.getId());
            mbrOrderItem.setOrderNo(orderNo);
            mbrOrderItem.setCourseCategoryId(mbrOrderPayVO.getCourseCategoryId());
            mbrOrderItem.setProductId(mbrOrderPayVO.getProductId());
            mbrOrderItem.setOrderType(mbrOrderPayVO.getOrderType());
            mbrOrderItem.setCourseMarketPrice(mbrOrderPayVO.getMarketPrice());
            mbrOrderItem.setCourseSellPrice(mbrOrderPayVO.getSellPrice());
            mbrOrderItem.setCreateDate(new Date());
            mbrOrderItemMapper.save(mbrOrderItem);

            // 保存订单日志
            MbrOrderLog courseOrderLog = new MbrOrderLog();
            courseOrderLog.setId(IDUtil.getId());
            courseOrderLog.setCreateDate(new Date());
            courseOrderLog.setOrderNo(orderNo);
            courseOrderLog.setOrderStatus(MbrOrder.ORDER_STATUS.NOT_PAY.getValue());
            courseOrderLog.setRemark(MbrOrder.ORDER_STATUS.NOT_PAY.getName());
            mbrOrderLogMapper.save(courseOrderLog);
        } else {
            MbrOrder mbrOrder = new MbrOrder();
            mbrOrder.setOrderNo(orderNo);
            mbrOrder.setPayMode(mbrOrderPayVO.getPayMode());
            mbrOrderMapper.update(mbrOrder);
        }

        // 微信、支付宝统一下单
        mbrOrderPayVO.setOrderNo(orderNo);
        Map<String, Object> returnMap = unifiedOrderOfAliAndWeChat(mbrOrderPayVO, request);
        return returnMap;
    }

    /**
     * 小程序商品统一下单
     *
     * @param mbrOrderPayVO 会员订单支付VO对象
     * @param request       request请求对象
     * @return
     */
    @Override
    public Map<String, Object> handleMbrOrderOfMiniProduct(MbrOrderPayVO mbrOrderPayVO, HttpServletRequest request) {
        // 如果订单号存在就直接下单
        String orderNo = mbrOrderPayVO.getOrderNo();
        if (StringUtils.isBlank(orderNo)) {
            // 保存订单数据
            orderNo = OrderNoWorker.get();
            MbrOrder mbrOrder = new MbrOrder();
            mbrOrder.setId(IDUtil.getId());
            mbrOrder.setOrderNo(orderNo);
            mbrOrder.setTotalAmt(mbrOrderPayVO.getTotalAmt());
            mbrOrder.setActualAmt(mbrOrderPayVO.getActualAmt());
            mbrOrder.setPayMode(mbrOrderPayVO.getPayMode());
            mbrOrder.setOrderStatus(MbrOrder.ORDER_STATUS.NOT_PAY.getValue());
            mbrOrder.setOrderRemark("App订单");
            mbrOrder.setOrderType(mbrOrderPayVO.getOrderType());
            mbrOrder.setUserId(mbrOrderPayVO.getUserId());
            mbrOrder.setCreateDate(new Date());
            mbrOrderMapper.save(mbrOrder);

            // 保存订单项表
            MbrOrderItem mbrOrderItem = new MbrOrderItem();
            mbrOrderItem.setId(IDUtil.getId());
            mbrOrderItem.setOrderNo(orderNo);
            mbrOrderItem.setCourseCategoryId(mbrOrderPayVO.getCourseCategoryId());
            mbrOrderItem.setProductId(mbrOrderPayVO.getProductId());
            mbrOrderItem.setOrderType(mbrOrderPayVO.getOrderType());
            mbrOrderItem.setCourseMarketPrice(mbrOrderPayVO.getMarketPrice());
            mbrOrderItem.setCourseSellPrice(mbrOrderPayVO.getSellPrice());
            mbrOrderItem.setCreateDate(new Date());
            mbrOrderItemMapper.save(mbrOrderItem);

            // 保存订单日志
            MbrOrderLog courseOrderLog = new MbrOrderLog();
            courseOrderLog.setId(IDUtil.getId());
            courseOrderLog.setCreateDate(new Date());
            courseOrderLog.setOrderNo(orderNo);
            courseOrderLog.setOrderStatus(MbrOrder.ORDER_STATUS.NOT_PAY.getValue());
            courseOrderLog.setRemark(MbrOrder.ORDER_STATUS.NOT_PAY.getName());
            mbrOrderLogMapper.save(courseOrderLog);
        } else {
            MbrOrder mbrOrder = new MbrOrder();
            mbrOrder.setOrderNo(orderNo);
            mbrOrder.setPayMode(mbrOrderPayVO.getPayMode());
            mbrOrderMapper.update(mbrOrder);
        }

        // 微信、支付宝统一下单
        BigDecimal actualAmt = mbrOrderPayVO.getActualAmt();
        // 小程序支付
        try {
            Map<String, Object> map = WeChatPayUtil.unifiedOrderOfMini(orderNo, actualAmt, "/order/anon/weChatNotify/MINI_PRODUCT_ORDER", "坚小持英语学院", mbrOrderPayVO.getOpenId(), request);
            return map;
        } catch (Exception e) {
            log.error("\r\n *********小程序支付报错 *********** \r\n{}", ExceptionUtils.getFullStackTrace(e));
            return null;
        }
    }


    /**
     * 阿里、微信统一下单工具方法
     *
     * @param mbrOrderPayVO 支付对象
     * @param request       请求对象
     * @return
     */
    private Map<String, Object> unifiedOrderOfAliAndWeChat(MbrOrderPayVO mbrOrderPayVO, HttpServletRequest request) {
        // 微信支付
        Integer payMode = mbrOrderPayVO.getPayMode();
        String orderNo = mbrOrderPayVO.getOrderNo();
        BigDecimal actualAmt = mbrOrderPayVO.getActualAmt();
        if (payMode.equals(MbrOrder.PAY_MODEL.WX_APP_PAY.getValue())) {
            try {
                Map<String, Object> map = WeChatPayUtil.unifiedOrderOfApp(orderNo, actualAmt, "/order/anon/weChatNotify/APP_COURSE_ORDER", "坚小持英语", request);
                return map;
            } catch (Exception e) {
                log.error("\r\n *********App微信支付报错 *********** \r\n{}", ExceptionUtils.getFullStackTrace(e));
                return null;
            }
        }

        // 支付宝支付
        if (payMode.equals(MbrOrder.PAY_MODEL.ALI_APP_PAY.getValue())) {
            // 初始化阿里支付对象
            AliPayPojo aliPayPojo = new AliPayPojo();
            aliPayPojo.setSubject("课程订单");
            aliPayPojo.setAsyNotifyUrl(PropConfig.getProperty(PropAttributes.THIRDPARTY_ALI_DOMAIN) + "/order/anon/aliNotify/appPay");
            try {
                aliPayPojo.setPassbackParams(URLEncoder.encode("APP_COURSE_ORDER", "utf-8"));
            } catch (UnsupportedEncodingException e) {
                log.error("\r\n *********App阿里支付报错 *********** \r\n{}", ExceptionUtils.getFullStackTrace(e));
                return null;
            }
            aliPayPojo.setAliAppId(AliPayUtil.ALI_APP_ID_APP);
            aliPayPojo.setAliAppPrivateKey(AliPayUtil.ALI_APP_PRIVATE_KEY_APP);
            aliPayPojo.setAliPayPublicKey(AliPayUtil.ALI_PAY_PUBLIC_KEY);
            try {
                Map<String, Object> map = AliPayUtil.alipayApp("坚小持英语", orderNo, "QUICK_MSECURITY_PAY", String.valueOf(actualAmt), aliPayPojo);
                return map;
            } catch (Exception e) {
                log.error("\r\n *********App阿里付报错 *********** \r\n{}", ExceptionUtils.getFullStackTrace(e));
                return null;
            }
        }

        return null;
    }

    /**
     * @param orderNo       原始订单号
     * @param transactionNo 商户订单号
     * @param payDate       支付成功实践
     */
    @Override
    public void handleNotifyOfPay(String orderNo, String transactionNo, Date payDate) {

        // 更新订单状态
        MbrOrder mbrOrder = mbrOrderMapper.getByOrderNo(orderNo);
        mbrOrder.setPayDate(payDate);
        mbrOrder.setModifyDate(new Date());
        mbrOrder.setTransactionNo(transactionNo);
        mbrOrder.setOrderStatus(MbrOrder.ORDER_STATUS.SUCCESS.getValue());
        mbrOrderMapper.update(mbrOrder);

        // 更新订单日志
        MbrOrderLog courseOrderLog = new MbrOrderLog();
        courseOrderLog.setId(IDUtil.getId());
        courseOrderLog.setCreateDate(new Date());
        courseOrderLog.setOrderNo(orderNo);
        courseOrderLog.setOrderStatus(MbrOrder.ORDER_STATUS.SUCCESS.getValue());
        courseOrderLog.setRemark(MbrOrder.ORDER_STATUS.SUCCESS.getName());
        mbrOrderLogMapper.save(courseOrderLog);

        // 课程信息开课
        if (mbrOrder.getOrderType().equals(0) && StringUtils.isNotBlank(mbrOrder.getUserId())) {
            // 查询课程信息,并初始化开课信息
            List<MbrOrderItem> orderItems = mbrOrderItemMapper.getByOrderNo(orderNo);
            if (CollectionUtils.isEmpty(orderItems)) {
                return;
            }
            Date nowDate = new Date();
            Date endDate = DateUtil.add(nowDate, 1, 1);
            MbrOrderItem mbrOrderItem = orderItems.get(0);
            mbrOrderItem.setCourseStartDate(nowDate);
            mbrOrderItem.setCourseEndDate(endDate);
            mbrOrderItemMapper.update(mbrOrderItem);

        }
    }

    /**
     * 会员订单支付VO对象
     *
     * @param mbrOrderPayVO 会员订单支付VO对象
     * @param request       request请求对象
     * @return
     */
    @Override
    public Map<String, Object> handleUnifiedOfMp(MbrOrderPayVO mbrOrderPayVO, HttpServletRequest request) {
        // TODO: 2/7/21 测试时打开注释即可
//        mbrOrderPayVO.setActualAmt(new BigDecimal("0.01"));
//        mbrOrderPayVO.setTotalAmt(new BigDecimal("0.01"));

        // 保存订单数据
        String orderNo = OrderNoWorker.get();
        MbrOrder mbrOrder = new MbrOrder();
        mbrOrder.setId(IDUtil.getId());
        mbrOrder.setOrderNo(orderNo);
        mbrOrder.setTotalAmt(mbrOrderPayVO.getTotalAmt());
        mbrOrder.setActualAmt(mbrOrderPayVO.getActualAmt());
        mbrOrder.setPayMode(mbrOrderPayVO.getPayMode());
        mbrOrder.setOrderStatus(MbrOrder.ORDER_STATUS.NOT_PAY.getValue());
        mbrOrder.setOrderRemark("公众号支付订单");
        mbrOrder.setOrderType(mbrOrderPayVO.getOrderType());
        mbrOrder.setOpenId(mbrOrderPayVO.getOpenId());
        mbrOrder.setCreateDate(new Date());
        mbrOrderMapper.save(mbrOrder);

        // 保存订单项表
        MbrOrderItem mbrOrderItem = new MbrOrderItem();
        mbrOrderItem.setId(IDUtil.getId());
        mbrOrderItem.setOrderNo(orderNo);
        mbrOrderItem.setCourseCategoryId(mbrOrderPayVO.getCourseCategoryId());
        mbrOrderItem.setProductId(mbrOrderPayVO.getProductId());
        mbrOrderItem.setOrderType(mbrOrderPayVO.getOrderType());
        mbrOrderItem.setCourseMarketPrice(mbrOrderPayVO.getMarketPrice());
        mbrOrderItem.setCourseSellPrice(mbrOrderPayVO.getSellPrice());
        mbrOrderItem.setCreateDate(new Date());
        mbrOrderItemMapper.save(mbrOrderItem);

        // 保存订单日志
        MbrOrderLog courseOrderLog = new MbrOrderLog();
        courseOrderLog.setId(IDUtil.getId());
        courseOrderLog.setCreateDate(new Date());
        courseOrderLog.setOrderNo(orderNo);
        courseOrderLog.setOrderStatus(MbrOrder.ORDER_STATUS.NOT_PAY.getValue());
        courseOrderLog.setRemark(MbrOrder.ORDER_STATUS.NOT_PAY.getName());
        mbrOrderLogMapper.save(courseOrderLog);

        // 微信小程序支付预下单
        Map<String, Object> returnMap = WeChatPayUtil.unifiedOrderOfPublicNumber(orderNo, mbrOrderPayVO.getActualAmt(),
                mbrOrderPayVO.getOpenId(),
                "/order/anon/weChatNotify/H5_MP_COURSE_ORDER",
                "坚小持英语",
                orderNo,
                request);
        return returnMap;
    }

    /**
     * @param mbrOrder 会员订单对象
     * @return
     */
    @Override
    public List<MbrOrderInfoVO> getOrdersOfPersonalCenter(MbrOrder mbrOrder) {
        // 查询订单
        List<MbrOrderInfoVO> mbrOrders = mbrOrderMapper.getByUserId(mbrOrder.getUserId());
        return mbrOrders;
    }
}
